contract SupplyChain {
address public admin;
mapping(address => bool) public authorizedEntities;
mapping(address => uint) public roles; // 0: ADMIN, 1: AUTHORIZER, 2: MANUFACTURER
struct Product {
string name;
address manufacturer;
bool isVerified;
}
mapping(uint => Product) public products;
constructor() {
admin = msg.sender;
roles[msg.sender] = 0; // Assign admin role to deployer
}
modifier onlyAdmin() {
require(roles[msg.sender] == 0, "Only admin can perform this action");
_;
}
modifier onlyAuthorized() {
require(authorizedEntities[msg.sender] || roles[msg.sender] == 0, "Not authorized");
_;
}
modifier onlyManufacturer(uint productId) {
require(msg.sender == products[productId].manufacturer || roles[msg.sender] == 0, "Only manufacturer can verify");
_;
}
function authorizeEntity(address entity, uint role) public onlyAdmin {
authorizedEntities[entity] = true;
roles[entity] = role;
}
function addProduct(uint productId, string memory name) public onlyAuthorized {
products[productId] = Product(name, msg.sender, false);
}
function verifyProduct(uint productId) public onlyManufacturer(productId) {
products[productId].isVerified = true;
}
}
contract MedicalRecords {
struct Record {
string diagnosis;
string treatment;
uint timestamp;
}
mapping(address => Record[]) public records;
function addRecord(string memory diagnosis, string memory treatment) public {
require(bytes(diagnosis).length > 0 && bytes(treatment).length > 0, "Invalid input");
records[msg.sender].push(Record(diagnosis, treatment, block.timestamp));
}
}
contract Voting {
mapping(address => bool) public hasVoted;
mapping(string => uint) public votes;
function vote(string memory candidate) public {
require(!hasVoted[msg.sender], "Already voted");
votes[candidate]++;
hasVoted[msg.sender] = true;
}
}
contract CredentialVerification {
struct Credential {
string degree;
string institution;
bool verified;
}
mapping(address => Credential) public credentials;
function addCredential(string memory degree, string memory institution) public {
credentials[msg.sender] = Credential(degree, institution, false);
}
function verifyCredential(address student) public {
credentials[student].verified = true;
}
}
contract Royalty {
struct Content {
string title;
address creator;
uint royalty;
}
mapping(uint => Content) public contentLibrary;
function addContent(uint id, string memory title, uint royalty) public {
contentLibrary[id] = Content(title, msg.sender, royalty);
}
function payRoyalty(uint contentId) public payable {
address creator = contentLibrary[contentId].creator;
uint amount = contentLibrary[contentId].royalty;
payable(creator).transfer(amount);
}
}
contract Charity {
mapping(address => uint) public donations;
uint public totalDonations;
function donate() public payable {
donations[msg.sender] += msg.value;
totalDonations += msg.value;
}
}
contract LandRegistry {
struct Land {
uint id;
address owner;
bool forSale;
}
mapping(uint => Land) public lands;
function registerLand(uint id) public {
lands[id] = Land(id, msg.sender, false);
}
function transferOwnership(uint id, address newOwner) public {
require(msg.sender == lands[id].owner, "Not authorized");
lands[id].owner = newOwner;
}
}
Decentralized Marketplaces:** Considerations for secure and fair payment management are crucial to avoid fraud in ownership transfers.
Explanation: Flash loan attacks exploit unsecured lending features in DeFi protocols, allowing attackers to borrow and repay large amounts of funds within a single transaction to manipulate the market, drain liquidity, or cause massive price swings.
Code Sample: Guarding Against Flash Loan Attacks with ReentrancyGuard
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
contract SecureLending is ReentrancyGuard {
mapping(address => uint) public balances;
function deposit() public payable {
balances[msg.sender] += msg.value;
}
function withdraw(uint amount) public nonReentrant {
require(balances[msg.sender] >= amount, "Insufficient balance");
balances[msg.sender] -= amount;
payable(msg.sender).transfer(amount);
}
}
This sample uses the nonReentrant modifier to prevent reentrancy attacks, which are common in flash loan exploit strategies.
Benefits:
Problems:
Insights:
nonReentrant modifier prevents recursive calls within the same transaction, which can be crucial in cases where functions affect balances.// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Voting {
struct Voter {
bytes32 commitment;
bool revealed;
uint8 vote;
}
address public owner;
uint256 public commitEndTime;
uint256 public revealEndTime;
mapping(address => Voter) public voters;
uint256 public yesVotes;
uint256 public noVotes;
event VoteCommitted(address indexed voter);
event VoteRevealed(address indexed voter, uint8 vote);
modifier onlyDuringCommitPhase() {
require(block.timestamp < commitEndTime, "Commit phase has ended");
_;
}
modifier onlyDuringRevealPhase() {
require(block.timestamp >= commitEndTime, "Reveal phase not started");
require(block.timestamp < revealEndTime, "Reveal phase has ended");
_;
}
constructor(uint256 _commitDuration, uint256 _revealDuration) {
owner = msg.sender;
commitEndTime = block.timestamp + _commitDuration;
revealEndTime = commitEndTime + _revealDuration;
}
function commitVote(bytes32 _commitment) external onlyDuringCommitPhase {
require(voters[msg.sender].commitment == bytes32(0), "Already committed");
voters[msg.sender].commitment = _commitment;
emit VoteCommitted(msg.sender);
}
function revealVote(uint8 _vote, string calldata _salt) external onlyDuringRevealPhase {
Voter storage voter = voters[msg.sender];
require(voter.commitment != bytes32(0), "No commitment found");
require(!voter.revealed, "Already revealed");
require(_vote == 1 || _vote == 0, "Vote must be 0 or 1");
bytes32 commitmentCheck = keccak256(abi.encodePacked(_vote, _salt));
require(commitmentCheck == voter.commitment, "Commitment does not match");
voter.vote = _vote;
voter.revealed = true;
if (_vote == 1) {
yesVotes++;
} else {
noVotes++;
}
emit VoteRevealed(msg.sender, _vote);
}
function getVotingResult() external view returns (string memory) {
require(block.timestamp >= revealEndTime, "Reveal phase not finished");
if (yesVotes > noVotes) {
return "Yes wins";
} else if (noVotes > yesVotes) {
return "No wins";
} else {
return "Tie";
}
}
function generateCommitment(uint8 _vote, string calldata _salt) external pure returns (bytes32) {
return keccak256(abi.encodePacked(_vote, _salt));
}
}